/*
  EOMono
  Copyright 2007, Adam Tauno Williams (Whitemice Consulting)
  License: LGPLv2  < http://www.gnu.org/licenses/lgpl-2.1.html >
 */
using System;
using System.IO;
using System.Xml;
using log4net;
using System.Collections;
using System.Collections.Generic;

namespace Whitemice.EOMono
{
  public static class EOModel
  {
    public static IDictionary<string, EOEntity> entityList = null;
    
    static EOModel()
    {
      entityList = new Dictionary<string, EOEntity>();
    }
        
    public static void AddEntity(EOEntity entity)
    {
      string name = entity.Name.ToLower();
      if (entityList.ContainsKey(name))
        throw new Exception(string.Format("Entity \"{0}\" already defined in model.", entity.Name));
      entityList.Add(name, entity);
      name = null;
    }
    
    public static EOEntity Entity(string name)
    {
      if ((name == null) || (name.Length == 0))
        return null;
      if (entityList.ContainsKey(name.ToLower()))
        return entityList[name.ToLower()];
      throw new Exception(string.Format("Request to model for non-existent entity \"{0}\".", name));
    }
    
    public static void Load(string path)
    {
      EOEntity  entity = null;
      string    alias, name, type;
      bool      magic, pkey;
      
      if (File.Exists(path))
      {
        using(NDC.Push("EOModelLoad"))
        {
          XmlTextReader  reader = new XmlTextReader(path);
          while (reader.Read())
          {
            switch (reader.NodeType)
            {
              case XmlNodeType.Document:
                break;
              case XmlNodeType.Element:
                IDictionary<string, string> attributes = new Dictionary<string,string>();
                string element                         = reader.Name;
                
                if (reader.HasAttributes)
                  for (int i = 0; i < reader.AttributeCount; i++) 
                  {
                    reader.MoveToAttribute(i);
                    attributes.Add(reader.Name, reader.Value);
                  }
                switch(element)
                {
                  case "object":
                    magic = false;
                    alias = null;
                    name = attributes["name"];
                    if (attributes.ContainsKey("isMagic"))
                      if (attributes["isMagic"] == "true")
                        magic = true;
                    if (attributes.ContainsKey("internalName"))
                      alias = attributes["internalName"];                                            
                     entity = new EOSQLEntity(name, magic, alias);
                   break;
                  case "attribute":
                    pkey = false;
                    type = "String";
                    alias = null;
                    if (attributes.ContainsKey("isKey"))
                      if (attributes["isKey"] == "true")
                        pkey = true;
                    if (attributes.ContainsKey("type"))
                      type = attributes["type"];
                    if (attributes.ContainsKey("alias"))
                      alias = attributes["alias"];                     
                    entity.AddField(attributes["name"], pkey, type, alias);                     
                    break;
                  case "relation":                 
                   break;
                }
                break;
              case XmlNodeType.EndElement:
                if (reader.Name == "object")
                {
                  if (entity.IsAliased)
                  {
                    EOManager.Log.DebugFormat("Adding entity {0} as {1} to model.", 
                                              entity.InternalName, 
                                              entity.Name);
                  } else 
                    {
                      EOManager.Log.DebugFormat("Adding entity {0} to model.", 
                                                entity.Name);
                    }
                  AddEntity(entity);
                }
                break;
              case XmlNodeType.Text:
                break;
            }
          }
        } // end NDC
      } else throw new System.IO.FileNotFoundException("Model file not found.", path);
    } // end Load
  } // end class
}
